import React, {useState, useMemo, useEffect, useCallback} from 'react';
import {View, Text, StyleSheet} from 'react-native';

// eslint-disable-next-line radix
const getDouble = num => parseInt(num * 100) / 100;

const Slider = ({
  onChange = () => {},
  max = 10, // 最大值
  min = 0, // 最小值
}) => {
  const [btnType, setBtnType] = useState(null); // 按钮类型， left right
  const [sliderWidth, setSliderWidth] = useState(0); // silder宽度

  const [touchStart, setTouchStart] = useState(0); // 按下按钮位置

  const [leftTrX, setLeftTrX] = useState(0); // 左按钮偏移量
  const [leftStartX, setLeftStartX] = useState(0); // 停止时位置， 抬起时设置为0

  const [rightTrX, setRightTrX] = useState(0); // 右按钮偏移量
  const [rightStartX, setRightStartX] = useState(0); // 停止时位置， 抬起时设置为0
  const leftTranslateX = useMemo(() => {
    let x = leftTrX + leftStartX;
    if (x < 0) {
      x = 0;
    }
    if (x > sliderWidth) {
      x = sliderWidth;
    }
    return x;
  }, [leftTrX, leftStartX, sliderWidth]);

  const rightTranslateX = useMemo(() => {
    let x = rightTrX + rightStartX + sliderWidth;
    if (x < 0) {
      x = 0;
    }
    if (x > sliderWidth) {
      x = sliderWidth;
    }
    return x;
  }, [rightTrX, rightStartX, sliderWidth]);

  /**
   * @description 滑块进度条宽度
   */
  const sliderBarprogressBarWidth = useMemo(() => {
    let w = rightTranslateX - leftTranslateX;
    return w < 0 ? -w : w;
  }, [rightTranslateX, leftTranslateX]);

  /**
   * @description 滑块进度条偏移量
   */
  const sliderBarprogressBarTranslateX = useMemo(() => {
    return rightTranslateX > leftTranslateX ? leftTranslateX : rightTranslateX;
  }, [rightTranslateX, leftTranslateX]);

  /**
   * @description 最大值最小值计算
   */
  const valueConfig = useMemo(() => {
    const difference = max - min;
    return {
      left: getDouble((difference * leftTranslateX) / sliderWidth + min),
      right: getDouble((difference * rightTranslateX) / sliderWidth + min),
    };
  }, [rightTranslateX, leftTranslateX, min, max, sliderWidth]);

  /**
   * @description 按钮按下后记录偏移量和按钮类型
   */
  const onTouchStart = useCallback(
    type => e => {
      setBtnType(type);
      setTouchStart(e.nativeEvent.pageX);
    },
    [],
  );

  /**
   * @description 手指移动中存储偏移量
   */
  const onTouchMove = useCallback(
    e => {
      const trx = e.nativeEvent.pageX - touchStart; // 按下开始后X位移偏移量
      if (btnType && btnType === 'left') setLeftTrX(trx);
      if (btnType && btnType === 'right') setRightTrX(trx);
    },
    [touchStart, btnType],
  );

  /**
   * @description 抬起后计算偏移量
   */
  const onTouchEnd = useCallback(
    e => {
      const x_ = e.nativeEvent.pageX - touchStart; // 位移偏差， 计算最终位置
      if (btnType && btnType === 'left') {
        let lst = leftStartX + x_; // 抬起时左按钮最终的位置
        if (lst <= 0) lst = 0; // 最左的位置了
        if (lst >= sliderWidth) lst = sliderWidth; // 最右的位置了
        setLeftStartX(lst);
      }

      if (btnType && btnType === 'right') {
        let lst = rightStartX + x_; // 抬起时左按钮最终的位置
        if (lst <= -sliderWidth) lst = -sliderWidth; // 最左的位置了
        if (lst >= 0) lst = 0; // 最右的位置了
        setRightStartX(lst);
      }
      setLeftTrX(0);
      setRightTrX(0);
      setBtnType(null);
    },
    [touchStart, sliderWidth, leftStartX, btnType, rightStartX],
  );

  /**
   * @description 计算滑块宽度
   */
  const onLayout = useCallback(e => {
    setSliderWidth(e.nativeEvent.layout.width - 24);
  }, []);

  /**
   * @description 通知外面滑块值发生变化了
   */
  useEffect(() => {
    onChange(valueConfig);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [valueConfig]);

  return (
    <View
      style={styles.sliderBox}
      onLayout={onLayout}
      onTouchMove={onTouchMove}
      onTouchEnd={onTouchEnd}
      onTouchCancel={onTouchEnd}>
      <View style={styles.sliderBar}>
        <View
          style={[
            styles.sliderBarprogressBar,
            {
              width: sliderBarprogressBarWidth,
              transform: [
                {
                  translateX: sliderBarprogressBarTranslateX,
                },
              ],
            },
          ]}></View>
      </View>
      <SliderButton
        onTouchStart={onTouchStart('left')}
        price={valueConfig.left}
        translateX={leftTranslateX}
      />
      <SliderButton
        onTouchStart={onTouchStart('right')}
        price={valueConfig.right}
        translateX={rightTranslateX}
      />
    </View>
  );
};

export default Slider;

const SliderButton = ({price = 0, translateX = 0, onTouchStart}) => {
  return (
    <View
      onTouchStart={onTouchStart}
      style={[
        styles.sliderRightBtn,
        {
          transform: [
            {
              translateX: translateX,
            },
          ],
        },
      ]}>
      <View style={styles.btns}>
        <View style={styles.priceBox}>
          <View style={styles.positionPrice}>
            <Text style={styles.priceText}>{price}</Text>
          </View>
        </View>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  sliderBox: {
    height: 24,
    position: 'relative',
    justifyContent: 'center',
    alignItems: 'center',
    paddingHorizontal: 12,
  },
  sliderLeftBtn: {
    width: 24,
    height: 24,
    borderRadius: 50,
    backgroundColor: '#444',
    position: 'absolute',
    left: 0,
    top: 0,
    shadowColor: '#444',
    shadowOffset: {
      width: 20,
      height: 20,
    },
    shadowOpacity: 1,
    shadowRadius: 3,
  },
  shadowStyles: {
    shadowOffset: {
      width: 10,
      height: 10,
    },
    shadowOpacity: 0.5,
    shadowRadius: 3,
  },
  sliderBar: {
    height: 3,
    width: '100%',
    backgroundColor: '#dedede',
  },
  sliderRightBtn: {
    width: 24,
    height: 24,
    borderRadius: 50,
    backgroundColor: '#fff',
    position: 'absolute',
    left: 0,
    top: 0,
    shadowOffset: {
      width: 10,
      height: 10,
    },
    shadowRadius: 20,
    shadowOpacity: 0.8,
    shadowColor: '#000',
    elevation: 10,
  },
  sliderBarprogressBar: {
    width: 100,
    height: '100%',
    backgroundColor: '#f0435b',
  },
  btns: {
    width: '100%',
    height: '100%',
    position: 'relative',
  },
  priceBox: {
    position: 'absolute',
    top: -20,
    width: '100%',
    justifyContent: 'center',
    alignItems: 'center',
    height: 20,
    lineHeight: 20,
  },
  positionPrice: {
    width: 60,
    // backgroundColor: '#f40',
    justifyContent: 'center',
    alignItems: 'center',
  },
  priceText: {
    color: '#f1435a',
    fontSize: 12,
    fontFamily: 'HKGrotesk-Bold',
  },
});
